(剑指Offer)面试题26:复杂链表的复制
题目:
请实现函数ComplexListNode* Clone(ComplexListNode* pHead),复制一个复杂链表。
在复杂链表中,每个结点除了有一个pNext指针指向下一个结点之外,还有一个pSibling指向链表中的任意结点或者NULL。
结点的定义如下:
struct ComplexListNode{ int val; ComplexListNode* pNext; ComplexListNode* pSibling; };
思路:
方法1:
复制原始链表上的每一个结点,并通过pNext连接起来;然后再设置每个结点的pSibling指针。
假设原始链表中某个结点N的pSibling指针指向结点S,那么就需要从头到尾遍历查找结点S,如果从原始链表的头指针开始,经过m步之后达到结点S,那么在复制链表中的结点N'的pSibling指针指向的结点也是距离复制链表s步的结点。通过这种办法就可以为复制链表上的每个结点设置pSibling指针。
时间复杂度:O(N^2)
方法2:
方法1是通过链表查找来得到pSibling指针所指向的结点,实际上我们可以通过空间换取时间,将原始链表和复制链表的结点通过哈希表对应起来,这样查找的时间就从O(N)变为O(1)。具体如下:
复制原始链表上的每个结点N创建N',然后把这些创建出来的结点用pNext连接起来。同时把<N,N'>的配对信息方法一个哈希表中;然后设置复制链表中的每个结点的pSibling指针,如果原始链表中结点N的pSibling指向结点S,那么在复制链表中,对应的N'应该指向S'。
时间复杂度:O(N)
方法3:
在不使用辅助空间的情况下实现O(N)的时间效率。
第一步:根据原始链表的每个结点N创建对应的N',然后将N‘通过pNext接到N的后面;
第二步:设置复制出来的结点的pSibling。假设原始链表上的N的pSibling指向结点S,那么其对应复制出来的N'是N->pNext指向的结点,同样S'也是结点S->pNext指向的结点。
第三步:把长链表拆分成两个链表,把奇数位置的结点用pNext连接起来的就是原始链表,把偶数位置的结点通过pNext连接起来的就是复制链表。
代码:
1、Hash方法:
struct ComplexListNode{ int val; ComplexListNode* pNext; ComplexListNode* pSibling; ComplexListNode():val(0),pNext(NULL),pSibling(NULL){}; }; typedef std::map<ComplexListNode*,ComplexListNode*> MAP; ComplexListNode* CloneNodes(ComplexListNode* pHead,MAP &hashNode){ ComplexListNode* pNode=new ComplexListNode(); ComplexListNode* p=pNode; ComplexListNode* tmp; while(pHead!=NULL){ tmp=new ComplexListNode(); tmp->val=pHead->val; p->pNext=tmp; hashNode[pHead]=tmp; pHead=pHead->pNext; p=p->pNext; } return pNode->pNext; } void SetSiblings(ComplexListNode* pHead,ComplexListNode* pCopy,MAP &hashNode){ while(pCopy!=NULL){ pCopy->pSibling=hashNode[pHead->pSibling]; pCopy=pCopy->pNext; pHead=pHead->pNext; } } ComplexListNode* ComplexListCopy(ComplexListNode* pHead){ ComplexListNode* pCopy; MAP hashNode; pCopy=CloneNodes(pHead,hashNode); SetSiblings(pHead,pCopy,hashNode); return pCopy; }
2、复制连接方法:
#include <iostream> using namespace std; struct ComplexListNode{ int val; ComplexListNode* pNext; ComplexListNode* pSibling; ComplexListNode(int x):val(x),pNext(NULL),pSibling(NULL){}; }; void CloneNodes(ComplexListNode* pHead){ ComplexListNode* pNode=pHead; ComplexListNode* pCloned; while(pNode!=NULL){ pCloned=new ComplexListNode(pNode->val); pNode->pNext=pCloned; pCloned->pNext=pNode->pNext; pNode=pCloned->pNext; } } void ConnectSiblingNodes(ComplexListNode* pHead){ ComplexListNode* pNode=pHead; ComplexListNode* pCloned; while(pNode!=NULL){ pCloned=pNode->pNext; if(pNode->pSibling!=NULL){ pCloned->pSibling=pNode->pSibling->pNext; } pNode=pCloned->pNext; } } ComplexListNode* ReconnectNodes(ComplexListNode* pHead){ ComplexListNode* pNode=pHead; ComplexListNode* pClonedHead=NULL; ComplexListNode* pClonedNode=NULL; if(pNode!=NULL){ pClonedHead=pClonedNode=pNode->pNext; pNode->pNext=pClonedNode->pNext; pNode=pNode->pNext; } while(pNode!=NULL){ pClonedNode->pNext=pNode->pNext; pClonedNode=pClonedNode->pNext; pNode->pNext=pClonedNode->pNext; pNode=pNode->pNext; } return pClonedHead; } ComplexListNode* Clone(ComplexListNode* pHead){ CloneNodes(pHead); ConnectSiblingNodes(pHead); return ReconnectNodes(pHead); }
在线测试OJ:
http://www.nowcoder.com/books/coding-interviews/f836b2c43afc4b35ad6adc41ec941dba?rp=1
AC代码:
/* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomListNode(int x) : label(x), next(NULL), random(NULL) { } }; */ class Solution { public: typedef std::map<RandomListNode*,RandomListNode*> MAP; RandomListNode* CloneNextNode(RandomListNode* pHead,MAP &hashNode){ RandomListNode* pCopy=new RandomListNode(0); RandomListNode* p=pCopy; RandomListNode* tmp; while(pHead!=NULL){ tmp=new RandomListNode(pHead->label); p->next=tmp; hashNode[pHead]=tmp; p=p->next; pHead=pHead->next; } return pCopy->next; } void setRandomNode(RandomListNode* pHead,RandomListNode* pCopy,MAP &hashNode){ while(pCopy!=NULL){ pCopy->random=hashNode[pHead->random]; pCopy=pCopy->next; pHead=pHead->next; } } RandomListNode* Clone(RandomListNode* pHead) { RandomListNode* pCopy; MAP hashNode; pCopy=CloneNextNode(pHead,hashNode); setRandomNode(pHead,pCopy,hashNode); return pCopy; } };
/* struct RandomListNode { int label; struct RandomListNode *next, *random; RandomListNode(int x) : label(x), next(NULL), random(NULL) { } }; */ class Solution { public: RandomListNode* Clone(RandomListNode* pHead) { CloneNodes(pHead); CloneRandom(pHead); return ReConnectNodes(pHead); } void CloneNodes(RandomListNode* pHead){ RandomListNode* pCloned; while(pHead!=NULL){ pCloned=new RandomListNode(pHead->label); pCloned->next=pHead->next; pHead->next=pCloned; pHead=pCloned->next; } } void CloneRandom(RandomListNode* pHead){ RandomListNode* pCloned; while(pHead!=NULL){ pCloned=pHead->next; if(pHead->random!=NULL){ pCloned->random=pHead->random->next; } pHead=pCloned->next; } } RandomListNode* ReConnectNodes(RandomListNode* pHead){ RandomListNode* pClonedHead=NULL; RandomListNode* pClonedNode=NULL; RandomListNode* pNode=pHead; if(pNode!=NULL){ pClonedHead=pClonedNode=pNode->next; pNode->next=pClonedNode->next; pNode=pNode->next; } while(pNode!=NULL){ pClonedNode->next=pNode->next; pClonedNode=pClonedNode->next; pNode->next=pClonedNode->next; pNode=pNode->next; } return pClonedHead; } };